<template>
  <div>
    <el-container class="container">
      <el-aside width="300px">
        <el-row>
          <el-col :span="5">
            <img title="logo" alt="logo" style="width: 60px;height: 60px" src="../../assets/mongo_logo.png">
          </el-col>
          <el-col :span="19">
            <el-popover placement="bottom" trigger="hover">
              <h1 class="title" :title="title" slot="reference">
                {{ title }}
              </h1>
              <el-row>
                <el-button @click="copyConnectionString" type="info" icon="el-icon-document-copy">
                  复制连接字符串
                </el-button>
              </el-row>
              <el-row>
                <el-button @click="beforeOpenEditConnectionDialog" type="info" icon="el-icon-star-on"
                           style="padding-right: 63px;margin-top: 5px;">
                  {{ editConnectionDialogTitle }}
                </el-button>
              </el-row>
              <el-row>
                <el-button @click="connectionInfoDialog = true" type="info" icon="el-icon-info"
                           style="padding-right: 66px;margin-top: 5px;">连接信息
                </el-button>
              </el-row>
              <el-row>
                <el-button @click="disConnect" type="danger" icon="el-icon-error"
                           style="padding-right: 66px;margin-top: 5px;">断开连接
                </el-button>
              </el-row>
            </el-popover>
          </el-col>
        </el-row>
        <el-row>
          <span class="custom-tree-node">
            <span style="margin-left: 10px">
              <i class="el-icon-coin"></i>
              <el-link :underline="false" @click="toDatabases"><span
                  style="font-size: 1.4em;font-weight: bold;margin-left: 5px">数据库</span></el-link>
            </span>
            <span>
              <el-link :underline="false" @click="refresh"><i class="el-icon-refresh"></i></el-link>
              <el-link :underline="false" @click="showAddDialog('新建数据库')" style="margin-left: 10px"><i
                  class="el-icon-plus"></i></el-link>
            </span>
          </span>
        </el-row>
        <el-row>
          <el-input v-model="searchValue" placeholder="Search"></el-input>
        </el-row>
        <el-row>
          <el-tree ref="databasesTree" :data="databases" :props="databasesProps"
                   @node-click="treeClick" node-key="name"
                   :filter-node-method="filterDatabasesTreeNode">
            <span class="custom-tree-node" slot-scope="{ node, data }">
              <span>
                <i v-if="data.collections != null" class="el-icon-coin"></i>
                <i v-else class="el-icon-folder"></i>
                {{ node.label }}
              </span>
              <span v-if="data.collections != null">
                <el-link :underline="false" @click="showAddDialog('新建集合', node.label)"><i
                    class="el-icon-plus"></i></el-link>
                <el-link style="margin-left: 10px" :underline="false" @click="showDropDialog(node.label, '删除数据库')"><i
                    class="el-icon-delete-solid"></i></el-link>
              </span>
              <span v-else>
                <el-link :underline="false" @click="showDropDialog(node.label, '删除集合', node.parent.data)"><i
                    class="el-icon-delete-solid"></i></el-link>
              </span>
            </span>
          </el-tree>
        </el-row>
      </el-aside>

      <!-- 添加collection和database对话框 -->
      <el-dialog :visible.sync="addDialog" width="30%" :close-on-click-modal="false"
                 @closed="closeAddDialog" @opened="openAddDialog">
        <div slot="title" style="font-size: 1.3em">
          <span>{{ addDialogType }}</span>
        </div>
        <el-form :model="addForm" label-position="top" size="small">
          <el-form-item v-if="addDialogType === '新建数据库'" label="数据库名" label-width="50px">
            <el-input v-model="addForm.databaseName" :autofocus="true" ref="addDatabaseNameInput"></el-input>
          </el-form-item>
          <el-form-item label="集合名" label-width="50px">
            <el-input v-model="addForm.collectionName" :autofocus="true" ref="addCollectionNameInput"></el-input>
          </el-form-item>
        </el-form>
        <span slot="footer" class="dialog-footer">
          <el-button @click="addDialog = false">取消</el-button>
          <el-button type="primary" @click="addConfirm" :disabled="addButtonDisabled">新建</el-button>
        </span>
      </el-dialog>

      <!-- 删除collection和database对话框 -->
      <el-dialog :visible.sync="dropDialog" width="30%" :close-on-click-modal="false"
                 @closed="closeDropDialog" @opened="openDropDialog">
        <div slot="title" style="font-size: 1.3em">
          <i class="el-icon-error"
             style="color: red; margin-right: 5px;"></i>{{ dropDialogType }}
        </div>
        <el-form :model="dropForm" label-position="top" size="small">
          <el-form-item label-width="50px">
            <template slot="label">
              <span style="font-weight: bold">请输入 "{{ dropLabel }}" 进行确认{{ dropDialogType }}</span>
            </template>
            <el-input v-model="dropForm.dropString" :autofocus="true" ref="dropInput"></el-input>
          </el-form-item>
        </el-form>
        <span slot="footer" class="dialog-footer">
          <el-button @click="dropDialog = false">取消</el-button>
          <el-button type="danger" @click="dropConfirm" :disabled="dropButtonDisabled">{{ dropDialogType }}</el-button>
        </span>
      </el-dialog>

      <!-- 编辑保存连接对话框 -->
      <el-dialog :visible.sync="editConnectionDialog" width="30%" :close-on-click-modal="false"
                 @closed="closeEditConnectionDialog" @opened="openEditConnectionDialog">
        <div slot="title" class="editConnectionDialogTitle">
          {{ editConnectionDialogTitle }}
        </div>
        <el-form :model="saveConnectionForm" label-position="top" size="small">
          <el-form-item label="连接名" label-width="50px">
            <el-input v-model="saveConnectionForm.name" :autofocus="true" ref="nameInput"></el-input>
          </el-form-item>
          <el-form-item label="分组名" label-width="50px">
            <el-select v-model="saveConnectionForm.groups" placeholder="请选择" clearable filterable
                       default-first-option>
              <el-option v-for="item in saveConnectionGroups" :key="item.id" :label="item.groupName" :value="item.id">
              </el-option>
            </el-select>
          </el-form-item>
        </el-form>
        <span slot="footer" class="dialog-footer">
          <el-button @click="editConnectionDialog = false">取消</el-button>
          <el-button type="primary" @click="saveConnection" :disabled="saveIsDisabled">保存</el-button>
        </span>
      </el-dialog>

      <!-- 连接信息对话框 -->
      <el-dialog :visible.sync="connectionInfoDialog" width="50%" :close-on-click-modal="false">
        <div slot="title" class="editConnectionDialogTitle">
          连接信息
        </div>
        <el-descriptions direction="vertical" :colon="false" :column="1">
          <el-descriptions-item v-for="(info, index) in connectionInfo" :key="index">
            <template slot="label">
              <span style="font-weight: bolder;">{{ info.name }}</span>
            </template>
            {{ info.value.toString() }}
          </el-descriptions-item>
        </el-descriptions>
        <span slot="footer" class="dialog-footer">
          <el-button @click="connectionInfoDialog = false">Close</el-button>
        </span>
      </el-dialog>
      <el-main>
        <el-header>
          <Header></Header>
        </el-header>
        <router-view v-on:refreshTreeList="refresh"/>
      </el-main>
    </el-container>

  </div>
</template>

<script>
import {getConnectInfo, syncDisConnect} from "@/api/connection";
import {createDatabaseAndCollection, dropDatabase, getTreeList} from "@/api/databases";
import {createCollection, dropCollection} from "@/api/collections";
import Header from "@/components/Header.vue";
import {getAllGroup} from "@/api/group";
import {addSaveConnectByConnectionId, editSaveConnectNameAndGroup} from "@/api/saveConnect";

export default {
  name: "Connection",
  components: {Header},
  data() {
    return {
      title: '',
      searchValue: '',
      databases: [],
      databasesProps: {
        children: 'collections',
        label: 'name'
      },
      // 0：打开添加Database对话框，1：打开添加Collection对话框
      addDialogType: 0,
      addDialog: false,
      addButtonDisabled: true,
      addForm: {
        databaseName: '',
        collectionName: ''
      },
      dropDialogType: '',
      dropDialog: false,
      dropButtonDisabled: true,
      dropLabel: '',
      dropForm: {
        dropString: '',
        dropDatabase: ''
      },
      editConnectionDialog: false,
      editConnectionDialogTitle: '',
      saveConnectionForm: {
        name: '',
        groups: null,
        id: null
      },
      saveConnectionGroups: [],
      saveIsDisabled: true,
      connectionInfoDialog: false,
      connectionInfo: [],
      //保存界面刷新时先执行的时间
      beforeUnload_time: 0,
      //保存浏览器刷新或关闭时执行的时间
      gap_time: 0
    }
  },
  watch: {
    searchValue: {
      handler(val) {
        this.$refs.databasesTree.filter(val);
      }
    },
    addForm: {
      handler() {
        if (this.addDialogType === 0) {
          this.addButtonDisabled = (this.addForm.databaseName === '' || this.addForm.collectionName === '')
        } else {
          this.addButtonDisabled = this.addForm.collectionName === ''
        }
      },
      deep: true
    },
    dropForm: {
      handler() {
        this.dropButtonDisabled = this.dropForm.dropString !== this.dropLabel;
      },
      deep: true
    },
    saveConnectionForm: {
      handler(newValue) {
        this.saveIsDisabled = !(newValue.name != null && newValue.name !== '' && newValue.groups != null)
      },
      deep: true
    },
    "$store.state.databaseName": {
      handler(newVal) {
        if (newVal !== null) {
          this.$refs.databasesTree.store.nodesMap[newVal].expanded = true
        }
      },
      deep: true
    },
    "$store.state.collectionName": {
      handler(newVal) {
        if (newVal !== null && this.$store.getters.getDatabaseName !== null) {
          this.$refs.databasesTree.store.nodesMap[newVal].checked = true
        }
      },
      deep: true
    },
    "$store.state.connectionId": {
      handler(newVal) {
        if (newVal === null) {
          this.$router.push('/')
        }
      },
      deep: true
    }
  },
  methods: {
    getTreeList() {
      getTreeList().then(res => {
        let databases = []
        res.data.forEach(item => {
          let database = {}
          let collections = []
          for (let key in item) {
            database.name = key
            item[key].forEach(value => {
              let collection = {}
              collection.name = value
              collections.push(collection);
            })
          }
          database.collections = collections
          databases.push(database)
        })
        this.databases = databases
      })
    },
    toDatabases() {
      const loading = this.$loading({
        lock: true,
        text: '加载数据库中...',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      });
      setTimeout(() => {
        loading.close();
        this.$router.push('/databases');
        this.$store.dispatch('SetDatabaseName', null)
        this.$store.dispatch('SetCollectionName', null)
      }, 1000);
    },
    refresh() {
      const loading = this.$loading({
        lock: true,
        text: '刷新中...',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      });
      setTimeout(() => {
        loading.close();
        this.getTreeList()
      }, 1000);
    },
    filterDatabasesTreeNode(value, data) {
      if (!value) return true;
      return data.name.indexOf(value) !== -1;
    },
    showAddDialog(type, label) {
      this.addDialog = true
      this.addDialogType = type
      if (label !== null && label !== undefined && label !== '') {
        this.addForm.databaseName = label
      }
    },
    openAddDialog() {
      if (this.addDialogType === '新建数据库') {
        this.$refs.addDatabaseNameInput.focus();
      } else {
        this.$refs.addCollectionNameInput.focus();
      }
    },
    closeAddDialog() {
      this.addForm = {
        databaseName: '',
        collectionName: ''
      }
      this.addDialog = false
      this.addButtonDisabled = true
    },
    addConfirm() {
      if (this.addDialogType === 0) {
        // database
        createDatabaseAndCollection(this.addForm.databaseName, this.addForm.collectionName).then(() => {
          const loading = this.$loading({
            lock: true,
            text: '创建中...',
            spinner: 'el-icon-loading',
            background: 'rgba(0, 0, 0, 0.7)'
          });
          setTimeout(() => {
            loading.close();
            this.addDialog = false
            this.$message.success("成功创建数据库！")
            this.refresh()
          }, 1000);
        }).catch(() => {
          this.$message.error("创建数据库失败！")
        })
      } else {
        // collection
        createCollection(this.$store.getters.getDatabaseName, this.addForm.collectionName).then(() => {
          const loading = this.$loading({
            lock: true,
            text: '创建中...',
            spinner: 'el-icon-loading',
            background: 'rgba(0, 0, 0, 0.7)'
          });
          setTimeout(() => {
            loading.close();
            this.$message.success("成功创建集合！")
            this.addDialog = false
            this.refresh()
          }, 1000);
        }).catch(() => {
          this.$message.error("创建集合失败！")
        })
      }
    },
    showDropDialog(label, type, data) {
      this.dropLabel = label
      this.dropDialogType = type
      this.dropDialog = true
      if (type === 1) {
        // collection
        this.dropForm.dropDatabase = data.name
      }
    },
    openDropDialog() {
      this.$refs.dropInput.focus();
    },
    closeDropDialog() {
      this.dropForm = {
        dropString: '',
        dropDatabase: ''
      }
      this.dropDialog = false
      this.dropButtonDisabled = true
    },
    dropConfirm() {
      if (this.dropDialogType === '删除数据库') {
        // database
        dropDatabase(this.dropLabel).then(() => {
          const loading = this.$loading({
            lock: true,
            text: '删除中...',
            spinner: 'el-icon-loading',
            background: 'rgba(0, 0, 0, 0.7)'
          });
          setTimeout(() => {
            loading.close();
            this.dropDialog = false
            this.$message.success("成功删除数据库！")
            this.refresh()
          }, 1000);
        }).catch(() => {
          this.$message.error("删除数据库失败！")
        })
      } else {
        // collection
        dropCollection(this.dropForm.dropDatabase, this.dropLabel).then(() => {
          const loading = this.$loading({
            lock: true,
            text: '删除中...',
            spinner: 'el-icon-loading',
            background: 'rgba(0, 0, 0, 0.7)'
          });
          setTimeout(() => {
            loading.close();
            this.dropDialog = false
            this.$message.success("成功删除集合！")
            this.refresh()
          }, 1000);
        }).catch(() => {
          this.$message.error("删除集合失败！")
        })
      }
    },
    treeClick(data, node) {
      if (data.collections != null) {
        // collections
        this.$router.push('/collections')
        this.$store.dispatch('SetDatabaseName', data.name)
        this.$store.dispatch('SetCollectionName', null)
      } else {
        // documents
        this.$router.push('/documents')
        this.$store.dispatch('SetDatabaseName', node.parent.data.name)
        this.$store.dispatch('SetCollectionName', data.name)
      }
    },
    copyConnectionString() {
      navigator.clipboard.writeText("mongodb://" + this.title).then(() => {
        this.$message.success('Copy成功')
      })
    },
    disConnect() {
      this.$confirm('确认断开连接？', '断开连接', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
        beforeClose: (action, instance, done) => {
          if (action === 'confirm') {
            instance.confirmButtonLoading = true;
            instance.confirmButtonText = '运行中...';
            setTimeout(() => {
              done();
              setTimeout(() => {
                instance.confirmButtonLoading = false;
              }, 300);
            }, 500);
          } else {
            done();
          }
        }
      }).then(() => {
        this.$store.dispatch("DisConnect", this.$store.getters.getConnectionId).then(() => {
          this.$router.push({path: '/'})
        })
      })
    },
    saveConnection() {
      // todo: 添加或修改连接信息
      const loading = this.$loading({
        lock: true,
        text: this.editConnectionDialogTitle + '中...',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      });
      setTimeout(() => {
        loading.close();
        if (this.saveConnectionForm.id === null) {
          // save
          addSaveConnectByConnectionId(this.saveConnectionForm, this.$store.getters.getConnectionId).then(() => {
            this.$message.success("成功保存连接！")
            this.editConnectionDialog = false
          }).catch(() => {
            this.$message.error("保存连接失败！")
          })
        } else {
          // edit
          editSaveConnectNameAndGroup(this.saveConnectionForm, this.$store.getters.getConnectionId).then(() => {
            this.$message.success("成功修改连接！")
            this.editConnectionDialog = false
          }).catch(() => {
            this.$message.error("修改连接失败！")
          })
        }
        this.getConnectionInfo();
      }, 1000);
    },
    beforeOpenEditConnectionDialog() {
      if (this.$store.getters.getToken === null) {
        this.$message({
          type: 'error',
          message: '请登录后再进行操作！'
        })
      } else {
        this.editConnectionDialog = true
      }
    },
    openEditConnectionDialog() {
      this.$refs.nameInput.focus();
      this.getConnectionInfo()
      getAllGroup().then(res => {
        this.saveConnectionGroups = res.data
      })
    },
    closeEditConnectionDialog() {
      this.saveConnectionForm = {
        name: '',
        groups: null,
        id: null
      }
    },
    getConnectionInfo() {
      getConnectInfo().then(res => {
        let stats = {
          name: "Stats",
          value: [
            res.data.databaseCount + " Databases",
            res.data.collectionCount + " Collections"
          ]
        }
        let host = {
          name: "Host",
          value: res.data.Host
        }
        let cluster = {
          name: 'Cluster',
          value: res.data.Cluster
        }
        let edition = {
          name: 'Edition',
          value: "MongoDB " + res.data.Edition
        }
        this.connectionInfo.push(stats, host, cluster, edition)
        if (res.data.id != null) {
          this.title = res.data.name
          this.saveConnectionForm.id = res.data.id
          this.saveConnectionForm.name = res.data.name
          this.saveConnectionForm.groups = res.data.groupId
          this.editConnectionDialogTitle = '编辑连接'
        } else {
          this.title = res.data.uri
          this.editConnectionDialogTitle = '保存连接'
        }
      }).catch(() => {
        this.$message.error("获取连接信息失败！")
      })
    },
    beforeunloadHandler() {
      this.beforeUnload_time = new Date().getTime()
    },
    // 强制退出或关闭浏览器时
    async unloadHandler() {
      this.gap_time = new Date().getTime() - this.beforeUnload_time
      // 关闭窗口
      if (this.gap_time < 10) {
        await syncDisConnect(this.$store.getters.getConnectionId)
      }
    }
  },
  beforeCreate() {
    // 未连接，跳转至首页
    if (this.$store.getters.getConnectionId === null) {
      this.$router.push('/')
    }
  },
  created() {
    this.getConnectionInfo()
    this.getTreeList()
    window.addEventListener('beforeunload', () => this.beforeunloadHandler())
    window.addEventListener('unload', () => this.unloadHandler())
  },
  beforeUpdate() {
    // 已断开连接，提示并跳转
    if (this.$store.getters.getConnectionId === null) {
      const loading = this.$loading({
        lock: true,
        text: '当前连接已断开，请重新连接！',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      });
      setTimeout(() => {
        loading.close();
        this.$router.push({path: '/'})
      }, 1000);
    }
  },
  destroyed() {
    window.removeEventListener('beforeunload', () => this.beforeunloadHandler())
    window.removeEventListener('unload', () => this.unloadHandler())
  }
}
</script>

<style scoped>
.container {
  min-height: 955px;
}

.title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  height: 60px;
  line-height: 60px;
  margin: 0;
}

.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-right: 8px;
}

.editConnectionDialogTitle {
  font-size: 1.3em;
  font-weight: bolder;
}
</style>
